package com.huatai.vba.grovvy.service;

import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.xml.ResourceEntityResolver;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.*;
import org.springframework.util.Assert;

import com.google.common.collect.Lists;
import com.huatai.vba.dal.model.VbaFileAction;
import com.huatai.vba.grovvy.base.*;
import com.huatai.vba.service.VbaFileActionService;

import groovy.lang.GroovyClassLoader;

public class TemplateLoader implements ApplicationContextAware {

	@Autowired
	private VbaFileActionService vbaFileActionService;

	/** 脚本ClassLoader */
	private static final GroovyClassLoader groovyClassLoader = new GroovyClassLoader(
			TemplateLoader.class.getClassLoader());

	/** 配置XML写入器 */
	private ConfigurationXMLWriter configurationXMLWriter;

	private List<DynamicBean> dynamicBeans = Lists.newArrayList();

	/** Spring 上下文环境 */
	private ConfigurableApplicationContext applicationContext;

	public void loadAllScripts() {
		this.load();
	}

	private void load() {
		String contextString = ConfigurationXMLWriter.toSpringString(dynamicBeans);
		if (StringUtils.isBlank(contextString)) {
			return;
		}
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(
				(BeanDefinitionRegistry) this.applicationContext.getBeanFactory());
		beanDefinitionReader.setResourceLoader(this.applicationContext);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this.applicationContext));
		beanDefinitionReader.loadBeanDefinitions(new InMemoryResource(contextString));

		// 添加BeanPostProcessor，主要用来确保CustomScriptFactoryPostProcessor生效
		// 会重新加载groovybean 以及实例化
		// String[] postProcessorNames =
		// applicationContext.getBeanFactory().getBeanNamesForType(BeanPostProcessor.class,
		// true, false);

		// for (String postProcessorName : postProcessorNames) {
		// applicationContext.getBeanFactory()
		// .addBeanPostProcessor((BeanPostProcessor)
		// applicationContext.getBean(postProcessorName));
		// }
		BeanPostProcessor customScriptFactoryPostProcessor = (BeanPostProcessor) applicationContext
				.getBean("customScriptFactoryPostProcessor");
		applicationContext.getBeanFactory().addBeanPostProcessor(customScriptFactoryPostProcessor);

		Object object = applicationContext.getBean("grovvyexecute");
		System.out.println(object.toString());
	}

	private void writeBean(VbaFileAction vbaFileAction) throws Exception {
		if (checkSyntax(vbaFileAction)) {
			DynamicBean bean = getDynamicBeanByTemplateContent(vbaFileAction);
			dynamicBeans.add(bean);
			// configurationXMLWriter.write(GroovyConstant.SPRING_TAG, bean);
		}
	}

	private boolean checkSyntax(VbaFileAction vbaFileAction) {
		try {
			groovyClassLoader.parseClass(vbaFileAction.getActionTemplateContent());
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	private DynamicBean getDynamicBeanByTemplateContent(VbaFileAction vbaFileAction) {
		DynamicBean bean = new DynamicBean();
		String scriptName = vbaFileAction.getActionTemplateName();
		Assert.notNull(scriptName, "脚本类名不能为空");
		bean.put("id", scriptName);
		bean.put("script-source", GroovyConstant.SCRIPT_SOURCE_PREFIX + scriptName);

		return bean;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = (ConfigurableApplicationContext) applicationContext;
	}

}
